﻿using AJWPFAdmin.Core;
using AJWPFAdmin.Core.Components.AJTable.ViewModels;
using AJWPFAdmin.Core.Components.Views;
using AJWPFAdmin.Core.Excel;
using AJWPFAdmin.Core.ExtensionMethods;
using AJWPFAdmin.Core.Models;
using AJWPFAdmin.Core.Models.EF.Tables;
using AJWPFAdmin.Core.Mvvm;
using AJWPFAdmin.Core.Utils;
using AJWPFAdmin.Services.EF;
using MaterialDesignExtensions.Controls;
using MaterialDesignThemes.Wpf;
using Microsoft.AspNetCore.Mvc;
using Prism.Commands;
using Prism.Services.Dialogs;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Data;
using AJWPFAdmin.Core.Excel;
using AJWPFAdmin.Core.Components.ViewModels;

namespace AJWPFAdmin.Modules.Common.ViewModels
{
    public class TabIndexToEnableConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value is int index)
            {
                return index >= parameter?.ToString().TryGetInt();
            }
            return false;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return null;
        }
    }

    public class TabIndexToVisibleConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value is int index)
            {
                if (index == 0)
                {
                    return Visibility.Collapsed;
                }
                if ("prev".Equals(parameter?.ToString()))
                {
                    return index <= 2 ? Visibility.Visible : Visibility.Collapsed;
                }
                if ("next".Equals(parameter?.ToString()))
                {
                    return index == 1 ? Visibility.Visible : Visibility.Collapsed;
                }
            }
            return Visibility.Collapsed;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return null;
        }
    }

    public class ImportExcelDialogViewModel : ViewModelBase, IDialogAware
    {

        #region 数据预览表格配置 


        private AJTableFetchOptions _fetchOptions;

        public AJTableFetchOptions FetchOptions
        {
            get
            {
                return _fetchOptions;
            }
            set
            {
                SetProperty(ref _fetchOptions, value);
            }
        }

        private List<AJTableColumnItem> _columns;

        public List<AJTableColumnItem> Columns
        {
            get { return _columns; }
            set { SetProperty(ref _columns, value); }
        }

        private AJTableSearchFormConfig _formConfig;

        public AJTableSearchFormConfig FormConfig
        {
            get { return _formConfig; }
            set { SetProperty(ref _formConfig, value); }
        }

        #endregion

        private AJTableExportProgressViewModel _importProgressModel;
        public AJTableExportProgressViewModel ImportProgressModel
        {
            get
            {
                return _importProgressModel;
            }
            set
            {
                SetProperty(ref _importProgressModel, value);
            }
        }

        private ObservableCollection<string> _importProgressMessages;
        public ObservableCollection<string> ImportProgressMessages
        {
            get
            {
                return _importProgressMessages;
            }
            set
            {
                SetProperty(ref _importProgressMessages, value);
            }
        }

        private bool _refreshFlag;

        private bool _processing;

        private List<object> _rows;

        private int _selectedIndex;

        public event Action<IDialogResult> RequestClose;

        public int SelectedIndex
        {
            get { return _selectedIndex; }
            set { SetProperty(ref _selectedIndex, value); }
        }

        public string Title => "数据导入向导";

        private DelegateCommand _loadExcelFileCmd;
        public DelegateCommand LoadExcelFileCmd =>
            _loadExcelFileCmd ?? (_loadExcelFileCmd = new DelegateCommand(ExecuteLoadExcelFileCmd));

        void ExecuteLoadExcelFileCmd()
        {
            var fileDialog = new Microsoft.Win32.OpenFileDialog
            {
                AddExtension = true,
                DefaultExt = ".xlsx",
                Filter = "excel 文件（.xlsx）|*.xlsx"
            };

            if (!fileDialog.ShowDialog().GetValueOrDefault())
            {
                return;
            }

            var fileName = fileDialog.FileName;

            var worker = new BackgroundWorker();

            var loading = new CommonLoading();
            loading.SetMessage("正在处理数据...");
            DialogHost.Show(loading, DialogIds.DialogWindow);

            worker.DoWork += (_, e) =>
            {
                e.Result = AJImport.LoadExcel(_options.ImportType, fileName, 10000);
            };

            worker.RunWorkerCompleted += async (_, e) =>
            {
                DialogHost.Close(DialogIds.DialogWindow);
                var pagedRet = e.Result as ProcessResult;
                if (!pagedRet.Success)
                {
                    AJCommonDialog.ShowDialog(new AJCommonDialogViewModel.AJCommonDialogParams
                    {
                        Title = "提示",
                        Message = pagedRet.Message,
                    });
                    return;
                }
                else
                {
                    _rows = pagedRet.Data as List<object>;
                    if (_rows.Count == 0)
                    {
                        AJCommonDialog.ShowDialog(new AJCommonDialogViewModel.AJCommonDialogParams
                        {
                            Title = "提示",
                            Message = "没有任何数据需要导入",
                        });
                        return;
                    }

                }

                SelectedIndex = 1;

                FetchOptions.RequestRefresh(false);
            };

            worker.RunWorkerAsync();

        }

        private DelegateCommand<string> _goCmd;
        public DelegateCommand<string> GoCmd =>
            _goCmd ?? (_goCmd = new DelegateCommand<string>(ExecuteGoCmd, CanExecuteGoCmd));

        void ExecuteGoCmd(string parameter)
        {
            if ("prev".Equals(parameter))
            {
                SelectedIndex--;
            }
            else
            {
                SelectedIndex++;
                if (SelectedIndex == 2)
                {
                    StartImportProgress();
                }
            }
        }

        public bool CanExecuteGoCmd(string parameter)
        {
            return !_processing;
        }


        private DelegateCommand _downloadTemplateCmd;
        public DelegateCommand DownloadTemplateCmd =>
            _downloadTemplateCmd ?? (_downloadTemplateCmd = new DelegateCommand(ExecuteDownloadTemplateCmd));

        async void ExecuteDownloadTemplateCmd()
        {

            var fileName = _options.TemplateFileName ?? $"导入模板";

            var fileDialog = new Microsoft.Win32.SaveFileDialog
            {
                CreatePrompt = true,
                OverwritePrompt = true,
                AddExtension = true,
                DefaultExt = ".xlsx",
                Filter = "excel 文件（.xlsx）|*.xlsx",
                FileName = fileName,
            };

            if (!fileDialog.ShowDialog().GetValueOrDefault())
            {
                return;
            }

            var result = await Task.Run(() =>
            {
                var sampleRows = _options.TemplateRowsHandler?.Invoke() ?? new List<object>();

                return AJExport.CreateExcel(sampleRows, fileDialog.FileName, fileName);
            });

            AJCommonDialog.ShowDialog(new AJCommonDialogViewModel.AJCommonDialogParams
            {
                Title = result.Success ? "提示" : "下载模板失败",
                Message = result.Success ? "下载成功" : result.Message,
            });
        }

        private AJTableImportOptions _options;
        private AJImportTemplate _importTemplate;
        private DbService db;
        public ImportExcelDialogViewModel(DbService dbIns)
        {
            SelectedIndex = 0;
            db = dbIns;

            ImportProgressModel = new AJTableExportProgressViewModel();
            ImportProgressMessages = new ObservableCollection<string>();

            FetchOptions = new AJTableFetchOptions
            {
                FetchOnLoaded = false,
                Handle = (formCfg, pageCfg) =>
                {
                    return Task.FromResult(new AJTableFetchResult
                    {
                        Total = _rows.Count,
                        HasNext = false,
                        Rows = _rows
                    });
                }
            };

            FormConfig = new AJTableSearchFormConfig
            {
                Schemas = new ObservableCollection<AJTableSearchFormSchema>
                {
                    new AJTableSearchFormSchema
                    {
                        Visible = Visibility.Collapsed,
                        Field = "file"
                    }
                },
                AdvFilterVisibility = System.Windows.Visibility.Collapsed,
                ExportVisibility = System.Windows.Visibility.Collapsed,
            };


        }

        public bool CanCloseDialog()
        {
            return !_processing;
        }

        public void OnDialogClosed()
        {

        }

        public void OnDialogOpened(IDialogParameters parameters)
        {
            parameters.TryGetValue("data", out _options);

            _importTemplate = AJImport.CreateTemplate(_options.ImportType, new List<object>());

            var columns = new List<AJTableColumnItem>();

            foreach (var item in _importTemplate.Headers)
            {
                columns.Add(new AJTableColumnItem
                {
                    DataIndex = item.Column,
                    Title = item.Title,
                });
            }

            this.Columns = columns;
        }

        private void StartImportProgress()
        {
            _processing = true;
            GoCmd?.RaiseCanExecuteChanged();

            ImportProgressModel.Current = 0;
            ImportProgressModel.Total = _rows.Count;
            ImportProgressMessages.Clear();

            ImportProgressMessages.Add("开始导入...");

            var worker = new BackgroundWorker
            {
                WorkerReportsProgress = true,
            };

            worker.DoWork += (_, e) =>
            {
                var index = 1;
                var success = 0;
                foreach (var item in _rows)
                {
                    if (_options.ImportDataItemProcessHandler == null)
                    {
                        worker.ReportProgress(index, new ProcessResult
                        {
                            Success = true,
                        });
                        index++;
                        success++;
                        Thread.Sleep(10);
                        continue;
                    }
                    var result = _options.ImportDataItemProcessHandler(item);
                    worker.ReportProgress(index, result);
                    if (result.Success)
                    {
                        success++;
                    }
                    index++;
                    Thread.Sleep(10);
                }
                e.Result = success;
            };

            worker.ProgressChanged += (_, e) =>
            {
                ImportProgressModel.Current = e.ProgressPercentage;
                var ret = e.UserState as ProcessResult;
                ImportProgressMessages.Insert(0, ret.Success
                    ? $"第 {e.ProgressPercentage} 行 导入成功!" : $"第 {e.ProgressPercentage} 行 导入失败:{ret.Message}");
            };

            worker.RunWorkerCompleted += async (_, e) =>
            {
                _processing = false;
                GoCmd?.RaiseCanExecuteChanged();

                if (e.Error != null)
                {
                    AJCommonDialog.ShowDialog(new AJCommonDialogViewModel.AJCommonDialogParams
                    {
                        Title = "导入失败",
                        Message = e.Error.Message,
                    });

                    return;
                }

                if (_options.ImportCompleteHandler != null)
                {
                    var loading = new CommonLoading();
                    loading.SetMessage("正在处理...");
                    DialogHost.Show(loading,DialogIds.DialogWindow);
                    try
                    {
                        var result = await _options.ImportCompleteHandler.Invoke();
                        if (!result.Success)
                        {
                            DialogHost.Close(DialogIds.DialogWindow);

                            AJCommonDialog.ShowDialog(new AJCommonDialogViewModel.AJCommonDialogParams
                            {
                                Title = "导入失败",
                                Message = result.Message,
                            });

                            return;
                        }
                    }
                    catch (Exception ex)
                    {
                        DialogHost.Close(DialogIds.DialogWindow);

                        var errMsg = ex.Message;

                        if(ex.InnerException != null)
                        {
                            errMsg += $"\r\n{ex.InnerException.Message}";
                        }

                        AJCommonDialog.ShowDialog(new AJCommonDialogViewModel.AJCommonDialogParams
                        {
                            Title = "导入失败",
                            Message = errMsg,
                            Detail = ex.StackTrace
                        });

                        return;
                    }
                    DialogHost.Close(DialogIds.DialogWindow);
                }

                var success = (int)e.Result;

                _refreshFlag = success > 0;

                var confirm = await CommonUtil.ShowConfirmDialogAsync(new ConfirmationDialogArguments
                {
                    Title = success == _rows.Count ? "全部导入成功" : success == 0 ? "全部导入失败" : $"部分导入成功",
                    Message = "继续导入还是退出向导?",
                    OkButtonLabel = "继续导入",
                    CancelButtonLabel = "退出",
                }, DialogIds.DialogWindow);

                if (confirm)
                {
                    SelectedIndex = 0;
                }
                else
                {
                    RequestClose?.Invoke(new DialogResult(_refreshFlag ? ButtonResult.OK : ButtonResult.Cancel));
                }
            };

            worker.RunWorkerAsync();
        }
    }
}
